package io.gitee.wiqer.simple;


import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.*;

@Slf4j
public class SolutionNC93_LRU {
    /**
     * lru design
     * @param operators int整型二维数组 the ops
     * @param k int整型 the k
     * @return int整型一维数组
     */
    private LinkedHashMap<Integer, Node> map3 = new LinkedHashMap<Integer, Node>(){
        @Override
        protected boolean removeEldestEntry(Map.Entry<Integer, Node> var1) {

            return  false;
        }
    };
    private LinkedHashMap<Integer, Integer> map = new LinkedHashMap<Integer, Integer>(){
        @Override
        protected boolean removeEldestEntry(Map.Entry<Integer, Integer> var1) {

            return  size()>k;
        }
    };
    private int k;
    public int[] LRU (int[][] operators, int k) {
        this.k = k;
        int len = (int) Arrays.stream(operators).filter(x -> x[0] == 2).count();
        int[] res = new int[len];
        for(int i = 0, j = 0; i < operators.length; i++) {
            if(operators[i][0] == 1) {
                set(operators[i][1], operators[i][2]);
            } else {
                res[j++] = get(operators[i][1]);
            }
        }
        return res;
    }
    private void set(int key, int val) {
            map.put(key,val );
    }

    private int get(int key) {
        if(map.containsKey(key)) {
           int val= map.get(key);
            map.remove(key);
            map.put(key,val);
            return val;
        }
        return -1;
    }
    public int[] LRU3 (int[][] operators, int k) {
        this.k = k;
        int len = (int) Arrays.stream(operators).filter(x -> x[0] == 2).count();
        int[] res = new int[len];
        for(int i = 0, j = 0; i < operators.length; i++) {
            if(operators[i][0] == 1) {
                set3(operators[i][1], operators[i][2]);
            } else {
                res[j++] = get3(operators[i][1]);
            }
        }
        return res;
    }

    private void set3(int key, int val) {
        if(map3.containsKey(key)) {
            Node n= map3.get(k);
            n.val = val;
            n.hot=n.hot+1;
        } else {
            if(map3.size() >= k){
                int minKey=0;
                int minHot=9999999;
                for(Map.Entry<Integer, Node> e:map3.entrySet()){
                    if(e.getValue().hot<minHot){
                        minHot=e.getValue().hot;
                        minKey=e.getKey();
                    }

                }
                map3.remove(minKey);
            }
            Node node = new Node(key, val);
            map3.put(key, node);

        }
    }

    private int get3(int key) {
        if(map3.containsKey(key)) {
            Node node = map3.get(key);
            node.hot=node.hot+1;
            return node.val;
        }
        return -1;
    }
     class Node{
        int key, val,hot=0;
        public Node(int key, int val) {
            this.key = key;
            this.val = val;
        }
    }
    /**
     * lru design
     * @param operators int整型二维数组 the ops
     * @param k int整型 the k
     * @return int整型一维数组
     */
    public int[] LRU2 (int[][] operators, int k) {
        // write code here
        Map<Integer, Integer> map = new LinkedHashMap<>();
        List<Integer> list = new LinkedList<>();
        for (int[] operator : operators) {
            int key = operator[1];
            switch(operator[0]) {
                case 1:
                    int value = operator[2];
                    if (map.size() < k) {
                        map.put(key, value);
                    } else {
                        Iterator it = map.keySet().iterator();
                        map.remove(it.next());
                        map.put(key, value);
                    }
                    break;
                case 2:
                    if (map.containsKey(key)) {
                        int val = map.get(key);
                        list.add(val);
                        map.remove(key);
                        map.put(key, val);
                    } else {
                        list.add(-1);
                    }
                    break;
                default:
            }
        }
        int[] res = new int[list.size()];
        int i = 0;
        for (int val : list) {
            res[i++] = val;
        }
        return res;
    }
    @Test
    public void test(){
        int[][] arr={{1,1,1}, {1,2,2},{2,1},{1,3,3},{2,2},{1,4,4},{2,1},{2,3},{2,4}};
        int[] reArr= LRU(arr,2);
        /**
         * [1,-1,-1,3,4]
         */
        System.out.println( new ArrayList(Collections.singletonList(reArr)).toString() );
    }
}
